<?php

require_once('Zend/Db/Table/Row/Abstract.php');
require_once('Zend/Db/Table/Abstract.php');
require_once('Zend/Db/Table.php');
require_once('Zend/Db/Expr.php');

/**
 * 
 * An OAuth nonce exists to prevent replay of a specific signed request, so that
 * an attacker may not intercept a specific request for later reuse. This security
 * consideration is twofold- first to ensure that every request has a unique nonce,
 * and secondly that the timestamp associated with that nonce falls within a certain
 * time range.
 * 
 * Given that Nonce's are highly transient, and we don't really want to bother with a
 * database table because of the inevitable number of joins and queries that we'll
 * have to do to verify a particular nonce, this class instead attempts to act as 
 * a fornted
 * 
 * @author michaelk
 *
 */
class Core_OAuth_Nonce
{
	/**
	 * Cache provider ID. See cache.ini
	 * 
	 * @var string
	 */
	const CACHE_NAME = 'oauth';
	
	/**
	 * Private static reference to our nonce cache.
	 * 
     * @return Zend_Cache_Core
	 */
	private static $cache;
	
	
	/**
	 * Cache helper.
	 * 
	 * @return Zend_Cache_Core
	 */
	private static function getCache () 
	{
		if ( !isset(self::$cache))
		{
			$cacheManager = Core_Resource::locate('cachemanager');
			self::$cache = $cacheManager->getCache( self::CACHE_NAME );
		}
		
		return self::$cache;
	}
	
    /**
     * Factory Method. Spits out an object that's tied to the database.
     *
     * @return Core_OAuth_Nonce
     */
    public static function factory( $nonce, $consumerKey, $timeoutInSeconds )
    {
    	$cache = self::getCache();
    	
    	$cache_key = self::createCacheKey($nonce, $consumerKey);
    	
    	$cache->save(true,$cache_key,array(), $timeoutInSeconds );
    }
    
    /**
     * This method tries to find whether a nonce has been used by this given consumer
     * ID, within the configured nonce timeout window.
     * 
     * @param string $nonce
     * @param string $consumerId
     * @return boolean
     */
    public static function hasNonce ( $nonce, $consumerKey )
    {
    	$cache = self::getCache();
    	
    	return $cache->test(self::createCacheKey($nonce, $consumerKey));
    }
	
	/**
	 * @inheritDoc
	 */
    protected function _doInsert()
    {
    	$this->timestamp = new Zend_Db_Expr('NOW()');
    	
    	parent::_doInsert();
    }
    
    /**
     * Simple helper method to create the cache key.
     * 
     * @param string $nonce
     * @param string $consumerKey
     */
    private static function createCacheKey ( $nonce, $consumerKey )
    {
    	$cache_key = sprintf("oauth_%s_%s", $consumerKey, $nonce);
    	$cache_key = preg_replace("/[^a-zA-Z0-9_]/", '', $cache_key);
    	return $cache_key;
    }
}